package com.xzy.spring.bbb;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.ResolvableType;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 如何获取ResolvableType实例
 *
 * @author xzy.xiao
 * @date 2023/3/8  20:01
 */
class GenericClass {

    private static final Logger log = LoggerFactory.getLogger(GenericClass.class);
    private Map<String, List<Integer>> map;
    private List<Integer> list;
    private Set<Integer> set;
    private Integer integer;

    public GenericClass() {
    }

    public GenericClass(Map<String, List<Integer>> map, List<Integer> list, Set<Integer> set, Integer integer) {
        this.map = map;
        this.list = list;
        this.set = set;
        this.integer = integer;
    }

    public void setMap(Map<String, List<Integer>> map) {
        this.map = map;
    }

    public Map<String, List<Integer>> getMap() {
        return map;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        System.out.println("\n========== 根据原始类型 Class 创建 ResolvableType ==========\n");
        test1();

        System.out.println("\n========== 根据构造器参数创建 ResolvableType ==========\n");
        test2();

        System.out.println("\n========== 根据成员变量创建 ResolvableType ==========\n");
        test3();

        System.out.println("\n========== 根据实例创建 ResolvableType ==========\n");
        test4();

        System.out.println("\n========== 根据方法参数创建 ResolvableType ==========\n");
        test5();

        System.out.println("\n========== 根据方法的返回值创建 ResolvableType ==========\n");
        test6();

        System.out.println("\n========== 根据原始类型信息创建 ResolvableType ==========\n");
        test7();
    }

    /**
     * 根据原始类型信息创建 ResolvableType
     */
    private static void test7() {
        ResolvableType resolvableType0 = ResolvableType.forRawClass(List.class);
        log.info("原始类型 List.class => {}", resolvableType0);

        ResolvableType resolvableType1 = ResolvableType.forRawClass(Set.class);
        log.info("原始类型 Set.class => {}", resolvableType1);

        ResolvableType resolvableType2 = ResolvableType.forRawClass(Map.class);
        log.info("原始类型 Map.class => {}", resolvableType2);

        ResolvableType resolvableType3 = ResolvableType.forRawClass(String.class);
        log.info("原始类型 String.class => {}", resolvableType3);

        ResolvableType resolvableType4 = ResolvableType.forRawClass(Integer.class);
        log.info("原始类型 Integer.class => {}", resolvableType4);
    }

    /**
     * 根据方法的返回值创建 ResolvableType
     *
     * @throws NoSuchMethodException -
     */
    private static void test6() throws NoSuchMethodException {
        Method method = GenericClass.class.getMethod("getMap");
        ResolvableType resolvableType = ResolvableType.forMethodReturnType(method);
        log.info("方法 Map<String, List<Integer>> getMap() 的返回值 => {}", resolvableType);
    }

    /**
     * 根据方法参数创建 ResolvableType
     *
     * @throws NoSuchMethodException -
     */
    private static void test5() throws NoSuchMethodException {
        Method method = GenericClass.class.getMethod("setMap", Map.class);
        ResolvableType resolvableType = ResolvableType.forMethodParameter(method, 0);
        log.info("方法 void setMap(Map<String, List<Integer>> map) 的第一个参数 => {}", resolvableType);
    }

    /**
     * 根据实例创建 ResolvableType
     */
    private static void test4() {
        GenericClass genericClass = new GenericClass();
        ResolvableType resolvableType = ResolvableType.forInstance(genericClass);
        log.info("实例类型 GenericClass => {}", resolvableType);
    }

    /**
     * 根据成员变量创建 ResolvableType
     */
    private static void test3() {
        Field[] fields = GenericClass.class.getDeclaredFields();

        ResolvableType resolvableType0 = ResolvableType.forField(fields[0]);
        log.info("成员变量 private static final Logger log => {}", resolvableType0);

        ResolvableType resolvableType1 = ResolvableType.forField(fields[1]);
        log.info("成员变量 private Map<String, List<Integer>> map => {}", resolvableType1);

        ResolvableType resolvableType2 = ResolvableType.forField(fields[2]);
        log.info("成员变量 private List<Integer> list => {}", resolvableType2);

        ResolvableType resolvableType3 = ResolvableType.forField(fields[3]);
        log.info("成员变量 private Set<Integer> set => {}", resolvableType3);

        ResolvableType resolvableType4 = ResolvableType.forField(fields[4]);
        log.info("成员变量 private Integer integer => {}", resolvableType4);
    }

    /**
     * 根据构造器参数创建 ResolvableType
     */
    private static void test2() {
        // 构造器：GenericClass(Map<String, List<Integer>> map, List<Integer> list, Set<Integer> set, Integer integer)
        Constructor<?> constructor = GenericClass.class.getDeclaredConstructors()[1];

        ResolvableType resolvableType0 = ResolvableType.forConstructorParameter(constructor, 0);
        log.info("构造器参数 Map<String, List<Integer>> => {}", resolvableType0);

        ResolvableType resolvableType1 = ResolvableType.forConstructorParameter(constructor, 1);
        log.info("构造器参数 List<Integer> list => {}", resolvableType1);

        ResolvableType resolvableType2 = ResolvableType.forConstructorParameter(constructor, 2);
        log.info("构造器参数 Set<Integer> => {}", resolvableType2);

        ResolvableType resolvableType3 = ResolvableType.forConstructorParameter(constructor, 3);
        log.info("构造器参数 Integer => {}", resolvableType3);

    }

    /**
     * 根据原始类型 Class 创建 ResolvableType
     */
    private static void test1() {
        Class<GenericClass> clazz = GenericClass.class;
        ResolvableType resolvableType = ResolvableType.forClass(clazz);
        log.info("原始类型 GenericClass => {}", resolvableType);
    }
}
